/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "form_render_impl.h"

#include "form_constants.h"
#include "form_render_service_extension.h"
#include "form_mgr_errors.h"
#include "form_supply_proxy.h"
#include "hilog_wrapper.h"
#include "service_extension.h"
#include "runtime.h"
#include "js_runtime.h"
#include "ui_content.h"
#include "form_surface_interface.h"
#include "event_handler.h"
namespace OHOS {
namespace AppExecFwk {
namespace FormRender {
namespace {
    constexpr int32_t RENDER_FORM_FAILED = -1;
}
using namespace AbilityRuntime;

sptr<FormRenderImpl> FormRenderImpl::instance_;

static OHOS::AbilityRuntime::ServiceExtension *FormRenderServiceCreator(const std::unique_ptr<Runtime> &runtime)
{
    HILOG_DEBUG("Create FormRenderServiceExtension");
    return  FormRenderServiceExtension::Create(runtime);
}

__attribute__((constructor)) void RegisterServiceExtensionCreator()
{
    HILOG_DEBUG("Set FormRenderServiceExtension creator");
    OHOS::AbilityRuntime::ServiceExtension::SetCreator(FormRenderServiceCreator);
}

FormRenderImpl::FormRenderImpl() = default;
FormRenderImpl::~FormRenderImpl() = default;

int32_t FormRenderImpl::RenderForm(const FormJsInfo &formJsInfo, const Want &want,
                                   const sptr<IRemoteObject> &callerToken)
{
    HILOG_INFO("%{public}s called.", __func__);
    sptr<IFormSupply> formSupplyClient = iface_cast<IFormSupply>(callerToken);
    if (formSupplyClient == nullptr) {
        HILOG_WARN("%{public}s warn, IFormSupply is nullptr", __func__);
        return ERR_APPEXECFWK_FORM_BIND_PROVIDER_FAILED;
    }

    HILOG_DEBUG("%{public}s come, connectId: %{public}d.", __func__,
        want.GetIntParam(Constants::FORM_CONNECT_ID, 0L));

    // auto infoIter = formRenderInfo_.find(formJsInfo.bundleName);
    // if (infoIter != formRenderInfo_.end()) {
    //     HILOG_INFO("Bundle exist in FRS, bundleName = %{public}s", formJsInfo.bundleName.c_str());
    //     return ERR_OK;
    // }

    int32_t result = InitForm(formJsInfo, want);
    if (result != ERR_OK) {
        return result;
    }

    formSupplyClient->OnRenderTaskDone(want);
    return ERR_OK;
}
int gflag = 0;
int32_t FormRenderImpl::InitForm(const FormJsInfo &formJsInfo, const Want &want)
{
    if (gflag == 0) {
        HILOG_INFO("Kee Init form, 0");
        gflag++;
    } else {
        HILOG_INFO("Kee Init form, return");
        return ERR_OK;
    }
    HILOG_INFO("Kee Init form, bundleName = %{public}s, abilityName = %{public}s, formName = %{public}s, moduleName = %{public}s, jsFormCodePath = %{public}s, formSrc = %{public}s", formJsInfo.bundleName.c_str(), formJsInfo.abilityName.c_str(), formJsInfo.formName.c_str(), formJsInfo.moduleName.c_str(), formJsInfo.jsFormCodePath.c_str(), formJsInfo.formSrc.c_str());
    // AbilityRuntime::Runtime::Options options;
    // options.bundleName = formJsInfo.bundleName;
    // options.codePath = Constants::LOCAL_CODE_PATH;
    // BundleInfo bundleInfo;
    std::shared_ptr<EventRunner> runner = EventRunner::GetMainEventRunner();
    auto eventHandlerMain = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
    // if (!runner) {
    //     HILOG_ERROR("Create runner failed!");
    //     return RENDER_FORM_FAILED;
    // }
    // options.eventRunner = runner;
    // options.hapPath = formJsInfo.jsFormCodePath;
    // options.loadAce = true;
    // options.isBundle = true;
    // runtime = AbilityRuntime::Runtime::Create(options);
    // if (!runtime) {
    //     HILOG_ERROR("create runtime Failed!");
    //     return RENDER_FORM_FAILED;
    // }
    context = std::make_shared<AbilityRuntime::ContextImpl>();
    if (!context) {
        HILOG_ERROR("Create context failed!");
        return RENDER_FORM_FAILED;
    }
    AppExecFwk::HapModuleInfo hapModuleInfo;
    hapModuleInfo.name = formJsInfo.moduleName;
    hapModuleInfo.hapPath = formJsInfo.jsFormCodePath;
    context->InitHapModuleInfo(hapModuleInfo);
    auto& nativeEngine = (static_cast<AbilityRuntime::JsRuntime&>(*runtime_)).GetNativeEngine();
    HILOG_ERROR("Kee Ace::UIContent::Create context = %{public}p nativeEngine = %{public}p", context.get(), &nativeEngine);

    uiContent_ = Ace::UIContent::Create(context.get(), &nativeEngine, true);
    uiContent_->SetIsCard(true);
    std::weak_ptr<Ace::UIContent> wUiContent = uiContent_;
    auto task = [wUiContent, formJsInfo, want]() {
        HILOG_INFO("Kee Ace::UIContent::task");
        auto uiContent = wUiContent.lock();
        if (uiContent) {
            HILOG_INFO("Kee Ace::UIContent::Initialize");
            uiContent->Initialize(nullptr, "/ets/widget/pages/card", nullptr);
            HILOG_INFO("Kee Ace::UIContent::Foreground");
            uiContent->Foreground();
            HILOG_INFO("Kee Ace::UIContent::Foreground over");
            Rosen::RSSurfaceNode* rsSurfaceNodePtr = nullptr;
            uiContent->GetCardRootNode(reinterpret_cast<void**>(&rsSurfaceNodePtr));
            if (rsSurfaceNodePtr == nullptr) {
                HILOG_ERROR("Kee SubContainer::RunCard surfaceNode is null");
                return;
            }
            HILOG_ERROR("Kee SubContainer::RunCard surfaceNode = %{public}p, name=%{public}s", rsSurfaceNodePtr,
                rsSurfaceNodePtr->GetName().c_str());
            sptr<IRemoteObject> proxy = want.GetRemoteObject("ohos.extra.param.key.process_on_add_surface");
            sptr<Ace::IFormSurfaceService> surfaceServiceProxy = iface_cast<Ace::IFormSurfaceService>(proxy);
            if (surfaceServiceProxy) {
                HILOG_INFO("HXW get surfaceServiceProxy success.");
                HILOG_INFO("HXW formInfo.bundleName: %{public}s", formJsInfo.bundleName.c_str());
                Want newWant;
                auto node = std::shared_ptr<Rosen::RSSurfaceNode>(rsSurfaceNodePtr);
                surfaceServiceProxy->ProcessAddSurface(newWant, formJsInfo, node);
            }
        } else {
            HILOG_INFO("Kee Ace::UIContent::Task content nullptr");
        }
        HILOG_INFO("Kee Ace::UIContent::task over");
    };

    if (eventHandlerMain) {
        eventHandlerMain->PostTask(task);
        HILOG_INFO("Kee MainThread::Init eventHandlerMain");
    } else {
        HILOG_INFO("Kee MainThread::Init eventHandlerMain PostTask task failed");
    }

    HILOG_ERROR("Kee Ace::UIContent::OK");
    return ERR_OK;
}

void FormRenderImpl::SetRuntime(AbilityRuntime::Runtime& runtime)
{
    runtime_ = &runtime;
}
}  // namespace FormRender
}  // namespace AppExecFwk
}  // namespace OHOS
